#ifndef COMPILE_AST_H
#define COMPILE_AST_H

#include <cstring>

typedef class ast *past;

class CompUnit;

class Decl;

class expr;

class intValue;

class parameter;

class VarDef;

class FuncDef;

class VarDecl;

class UnaryExp;

class type;

class If_Else;

class VarDecl_list;

class FuncRParams_list;

class FuncDef_para;

class Block_list;

class Assign_Stmt;

class Return_Stmt;

class IfElse_Stmt;

class While_Stmt;

class ast {
public:
    char *strValue;
    char *nodeType;
    int ivalue;
    int loc;
    past next;
    past left;
    past right;
    bool ifJPC;
    bool whileJPC;
    int blInIf;
    int blInWhile;

    class Visitor {
    public:
        virtual void visit(CompUnit *) = 0;

        virtual void visit(intValue *) = 0;

        virtual void visit(Decl *) = 0;

        virtual void visit(VarDecl *) = 0;

        virtual void visit(expr *) = 0;

        virtual void visit(parameter *) = 0;

        virtual void visit(VarDef *) = 0;

        virtual void visit(FuncDef *) = 0;

        virtual void visit(UnaryExp *) = 0;

        virtual void visit(type *) = 0;

        virtual void visit(If_Else *) = 0;

        virtual void visit(VarDecl_list *) = 0;

        virtual void visit(FuncRParams_list *) = 0;

        virtual void visit(FuncDef_para *) = 0;

        virtual void visit(Block_list *) = 0;

        virtual void visit(Assign_Stmt *) = 0;

        virtual void visit(Return_Stmt *) = 0;

        virtual void visit(IfElse_Stmt *) = 0;

        virtual void visit(While_Stmt *) = 0;
    };

    static past newNum(int value);

    static past newExpr(int oper, past left, past right);

    static past newDoubleExpr(char *logic_oper, past left, past right);

    static past newBasicNode(char *nodeType, past left, past right, past next);

    static past newNextNode(char *nodeType, past older, past younger);

    static past newTypeNode(char *strVal);

    static past newIDNode(char *strVal);

    virtual void accept(Visitor *) = 0;

    static void showAst(past node, int nest);

    static void genSym(past node);

    static void genCode(past node);

    static void semanticCheck(past node);

    static past newAstNode(char *);

    virtual ~ast() = default;
};

extern ast *node;

class CompUnit : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class Decl : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class expr : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class parameter : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class VarDef : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class FuncDef : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class UnaryExp : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class type : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class VarDecl : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};


class VarDecl_list : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class FuncRParams_list : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class FuncDef_para : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class Block_list : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class Assign_Stmt : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class Return_Stmt : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class intValue : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class IfElse_Stmt : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class If_Else : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

class While_Stmt : public ast {
public:
    void accept(Visitor *v) override {
        v->visit(this);
    }
};

extern char *whichFunc;
extern char *whichVarDecl;

#endif //COMPILE_AST_H
